package dashboard

import (
	model "aggregation/model/dashboard"
	"aggregation/store"
	"aggregation/store/postgres"
	"aggregation/store/redis"
	"context"
	"time"
)

type user struct {
	UserUnBindBike store.ICounter
	UserBindBike   store.ICounter
	UserComplain   store.ICounter
	UserIncrease   store.ICounter
	UserActive     store.ICounter

	UserUnBindBikeCache store.ICache
	UserBindBikeCache   store.ICache
	UserComplainCache   store.ICache
	UserIncreaseCache   store.ICache
}

var User = &user{
	UserIncrease:   postgres.UserCount,
	UserBindBike:   postgres.UserBindBike,
	UserUnBindBike: postgres.UserUnbindBike,
	UserComplain:   postgres.UserComplain,
	UserActive:     postgres.UserActive,

	UserUnBindBikeCache: redis.UserUnbindBike,
	UserBindBikeCache:   redis.UserBindBikeCache,
	UserIncreaseCache:   redis.UserIncrease,
	UserComplainCache:   redis.UserComplain,
}

func (a *user) AppUserBoard(ctx context.Context) (model.UserBoardResponse, error) {
	var (
		board model.UserBoardResponse
		err   error
	)
	// 全部用户
	board.User, _ = a.UserIncrease.Count(ctx)
	board.BindUser, _ = a.UserBindBike.Count(ctx)
	board.UnbindUser, _ = a.UserUnBindBike.Count(ctx)
	board.ShareUser, _ = postgres.UserCount.ShareUser(ctx)
	now := time.Now()
	// 昨日新增
	board.Day = dayIncrease(ctx, now.AddDate(0, 0, -1), a.UserIncreaseCache, a.UserIncrease)
	// 本月新增
	board.Month = monthIncrease(ctx, now, a.UserIncreaseCache, a.UserIncrease)
	// 今年新增
	board.Year = yearIncrease(ctx, now, a.UserIncreaseCache, a.UserIncrease)
	return board, err
}

func (a *user) AppUserWave(ctx context.Context, period model.PERIOD) (model.UserWaveResponse, error) {
	var (
		wave model.UserWaveResponse
	)
	now := time.Now()
	switch period {
	case model.MONTH:
		wave = model.UserWaveResponse{
			Period:      period,
			OwnedBike:   monthUserWave(ctx, now, a.UserBindBikeCache, a.UserBindBike),
			UnownedBike: monthUserWave(ctx, now, a.UserUnBindBikeCache, a.UserUnBindBike),
		}
	case model.YEAR:
		wave = model.UserWaveResponse{
			Period:      period,
			OwnedBike:   yearUserWave(ctx, a.UserBindBikeCache, a.UserBindBike),
			UnownedBike: yearUserWave(ctx, a.UserUnBindBikeCache, a.UserUnBindBike),
		}
	default:
		wave = model.UserWaveResponse{
			Period:      "day",
			OwnedBike:   dayUserWave(ctx, now, a.UserBindBikeCache, a.UserBindBike),
			UnownedBike: dayUserWave(ctx, now, a.UserUnBindBikeCache, a.UserUnBindBike),
		}
	}
	return wave, nil
}

func (a *user) ComplainBoard(ctx context.Context) (model.UserComplaintBoardResponse, error) {
	var (
		board model.UserComplaintBoardResponse
	)
	total, _ := a.UserComplain.Count(ctx)
	now := time.Now()
	day := dayIncrease(ctx, now.AddDate(0, 0, -1), a.UserComplainCache, a.UserComplain)
	// 本月新增
	month := monthIncrease(ctx, now, a.UserComplainCache, a.UserComplain)
	// 今年新增
	year := yearIncrease(ctx, now, a.UserComplainCache, a.UserComplain)
	board = model.UserComplaintBoardResponse{
		Complaint: total,
		Day:       day,
		Month:     month,
		Year:      year,
	}
	return board, nil
}

func (a *user) ComplainWave(ctx context.Context, period model.PERIOD) (model.UserComplaintWaveResponse, error) {
	var (
		wave model.UserComplaintWaveResponse
	)
	if period == "" {
		period = model.DAY
	}
	wave.Period = period
	switch period {
	case model.MONTH:
		wave.Complaint = monthWave(ctx, time.Now(), a.UserComplainCache, a.UserComplain)
	case model.YEAR:
		wave.Complaint = yearWave(ctx, a.UserComplainCache, a.UserComplain)
	default:
		wave.Complaint = dayWave(ctx, time.Now(), a.UserComplainCache, a.UserComplain)
	}
	return wave, nil
}

func (a *user) ActiveUserBoard(ctx context.Context) (model.ActiveUserBoardResponse, error) {
	var (
		board model.ActiveUserBoardResponse
	)
	board = model.ActiveUserBoardResponse{
		TopActive: postgres.UserActive.MaxCount(ctx),
		Day:       dayIncrease(ctx, time.Now().AddDate(0, 0, -1), nil, a.UserActive),
		Month:     monthIncrease(ctx, time.Now(), nil, a.UserActive),
		Year:      yearIncrease(ctx, time.Now(), nil, a.UserActive),
	}
	return board, nil
}

func (a *user) ActiveUserWave(ctx context.Context, period model.PERIOD) (model.ActiveUserWaveResponse, error) {
	var (
		wave model.ActiveUserWaveResponse
	)
	if period.String() == "year" {
		wave = model.ActiveUserWaveResponse{
			Period:     period,
			ActiveUser: yearWave(ctx, nil, a.UserActive),
		}
	} else if period.String() == "month" {
		wave = model.ActiveUserWaveResponse{
			Period:     period,
			ActiveUser: monthWave(ctx, time.Now(), nil, a.UserActive),
		}
	} else {
		wave = model.ActiveUserWaveResponse{
			Period:     period,
			ActiveUser: dayWave(ctx, time.Now().AddDate(0, 0, -1), nil, a.UserActive),
		}
	}

	return wave, nil
}

func (a *user) UserSummary(ctx context.Context) model.UserSummaryResponse {
	total, _ := a.UserIncrease.Count(ctx)
	bind, _ := a.UserBindBike.Count(ctx)
	unbind, _ := a.UserUnBindBike.Count(ctx)
	share, _ := postgres.UserCount.ShareUser(ctx)
	return model.UserSummaryResponse{
		Total:  total,
		Bind:   bind,
		Share:  unbind,
		Unbind: share,
	}
}
